package com.core.api;

import android.text.TextUtils;
import android.view.View;
import android.widget.ProgressBar;
import com.core.util.B5MCacheManage;
import com.core.util.B5MLog;
import com.core.util.B5MNetworkUtils;
import com.core.util.Constants;
import com.core.widget.pulltorefresh.PullToRefreshListView;
import com.cptravel.R;
import com.cptravel.application.MainApplication;
import com.cptravel.tool.UserInfoManage;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.apache.http.Header;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public abstract class B5MBaseRequest<K extends B5MBaseResponse>
{
    AsyncHttpClient asyncHttpClient;
    public static final String SUCCESS = "succ";
    public static final String MESSAGE = "msg";
    public static final String ERROR = "errorcode";
    public static final String RESULT = "result";
    private static final String TAG = "DOPOST";
    public K response;
    private ApiListenrDefaultImpl apiListenrDefaultImpl;
    private boolean isForceLoad = false;
    //
    private StringBuilder requestStringBuilder;
    private String url;
    private PullToRefreshListView pullToRefreshListView;
    private ProgressBar progressBar;
    //
    public final static String IMAGE_KEY = "img_b5m";
    //
    public final String FLAG_SUCCESS = "1";
    public final String FLAG_ERROR = "0";
    private boolean isExtraUrl;
    private boolean isStarted;

    public B5MBaseRequest(ApiListenrDefaultImpl apiListenrDefaultImpl, ProgressBar progressBar)
    {
        // TODO Auto-generated constructor stub
        this.apiListenrDefaultImpl = apiListenrDefaultImpl;
        this.progressBar = progressBar;
    }

    public B5MBaseRequest(ApiListenrDefaultImpl apiListenrDefaultImpl, ProgressBar progressBar, PullToRefreshListView pullToRefreshListView)
    {
        super();
        this.apiListenrDefaultImpl = apiListenrDefaultImpl;
        this.progressBar = progressBar;
        this.pullToRefreshListView = pullToRefreshListView;
    }

    public boolean isExtraUrl()
    {
        return isExtraUrl;
    }

    public void setExtraUrl(boolean isExtraUrl)
    {
        this.isExtraUrl = isExtraUrl;
    }

    private void init()
    {
        // TODO Auto-generated method stub
        asyncHttpClient = new AsyncHttpClient();
        asyncHttpClient.setTimeout(5000);
        initResponse();
        apiListenrDefaultImpl.setProgressBar(progressBar);
        if (progressBar != null)
        {
            progressBar.setVisibility(View.VISIBLE);
        }
        if (response instanceof B5MBasePaggingResponse)
        {
            ((B5MBasePaggingResponse<?>) response).setPullToRefreshListView(pullToRefreshListView);
        }
    }

    private void setParams()
    {
        Map<String, Object> map = new HashMap<String, Object>();
        if (UserInfoManage.getInstance().isLogined())
        {
            map.put("userid", UserInfoManage.getInstance().getUser().getUserid());
        }
        setApiBody(map);
        requestStringBuilder = new StringBuilder();
        if (!map.isEmpty())
        {
            requestStringBuilder.append("&");
            for (Entry<String, Object> entry : map.entrySet())
            {
                try
                {
                    requestStringBuilder.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue() + "", HTTP.UTF_8)).append("&");
                }
                catch (UnsupportedEncodingException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            requestStringBuilder.deleteCharAt(requestStringBuilder.length() - 1);
        }
        url = !isExtraUrl() ? Constants.HOST + "?m=" + getApiMethod() + requestStringBuilder.toString() : url;
    }

    public abstract Class<K> getResponseClass();

    private void initResponse()
    {
        if (null == response)
        {
            try
            {
                response = getResponseClass().newInstance();
                apiListenrDefaultImpl.setB5mBaseResponse(response);
            }
            catch (InstantiationException e)
            {
                e.printStackTrace();
            }
            catch (IllegalAccessException e)
            {
                e.printStackTrace();
            }
        }
    }

    public void start()
    {
        isStarted = true;
        if (!beforePost())
        {
            isStarted = false;
            return;
        }
        asyncHttpClient.get(url, new JsonHttpResponseHandler()
        {
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response)
            {
                // TODO Auto-generated method stub
                super.onSuccess(statusCode, headers, response);
                isStarted = false;
                parseJsonObjectResult(response);
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONArray response)
            {
                // TODO Auto-generated method stub
                super.onSuccess(statusCode, headers, response);
                isStarted = false;
                parseJsonArrayResult(response);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse)
            {
                // TODO Auto-generated method stub
                super.onFailure(statusCode, headers, throwable, errorResponse);
                isStarted = false;
                if (statusCode == 200)
                {
                    parseErrorResult(errorResponse);
                }
                else
                {
                    B5MLog.i(TAG, "response--->" + throwable.getMessage());
                    apiListenrDefaultImpl.onFail(0, throwable.getMessage());
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable)
            {
                // TODO Auto-generated method stub
                super.onFailure(statusCode, headers, responseString, throwable);
                isStarted = false;
                if (statusCode == 200)
                {
                    apiListenrDefaultImpl.onSuccess(response);
                }
                else
                {
                    B5MLog.i(TAG, "response2--->statusCode=" + statusCode + " " + throwable.getMessage());
                    apiListenrDefaultImpl.onFail(0, throwable.getMessage());
                }
            }
        });
    }

    private boolean beforePost()
    {
        if (asyncHttpClient == null)
        {
            init();
        }
        setParams();
        B5MLog.i(TAG, "url=" + url + "\nbody--->" + requestStringBuilder.toString());
        // 是否读缓存数据
        if (isNeedCache() && !isForceLoad)
        {
            String cacheStr = B5MCacheManage.getInstance().readObject(url);
            if (!TextUtils.isEmpty(cacheStr))
            {
                try
                {
                    // jsonArray
                    if (cacheStr.startsWith("["))
                    {
                        JSONArray jsonArray = new JSONArray(cacheStr);
                        response.parseJsonArray(jsonArray);
                    }
                    else
                    // jsonObject
                    {
                        JSONObject jsonObject = new JSONObject(cacheStr);
                        response.parseJsonObject(jsonObject);
                    }
                }
                catch (JSONException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return false;
            }
        }
        if (!B5MNetworkUtils.isNetworkAvailabelAddition())
        {
            apiListenrDefaultImpl.onFail(0, MainApplication.getInstance().getString(R.string.networkisunavailable));
            return false;
        }
        return true;
    }

    /**
     * 上传文件
     *
     * @param file
     */
    public void uploadFile(File file)
    {
        if (!beforePost())
        {
            return;
        }
        RequestParams requestParams = new RequestParams();
        try
        {
            requestParams.put("pic", file);
        }
        catch (FileNotFoundException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        asyncHttpClient.post(url, requestParams, new JsonHttpResponseHandler()
        {
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response)
            {
                // TODO Auto-generated method stub
                super.onSuccess(statusCode, headers, response);
                parseJsonObjectResult(response);
            }

            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONArray response)
            {
                // TODO Auto-generated method stub
                super.onSuccess(statusCode, headers, response);
                parseJsonArrayResult(response);
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse)
            {
                // TODO Auto-generated method stub
                super.onFailure(statusCode, headers, throwable, errorResponse);
                if (statusCode == 200)
                {
                    parseErrorResult(errorResponse);
                }
                else
                {
                    B5MLog.i(TAG, "response--->" + throwable.getMessage());
                    apiListenrDefaultImpl.onFail(0, throwable.getMessage());
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable)
            {
                // TODO Auto-generated method stub
                super.onFailure(statusCode, headers, responseString, throwable);
                if (statusCode == 200)
                {
                    apiListenrDefaultImpl.onSuccess(response);
                }
                else
                {
                    B5MLog.i(TAG, "response2--->statusCode=" + statusCode + " " + throwable.getMessage());
                    apiListenrDefaultImpl.onFail(0, throwable.getMessage());
                }
            }
        });
    }

    public boolean isForceLoad()
    {
        return isForceLoad;
    }

    /**
     * 在需要缓存数据即isNeedCache()为true的情况下有效，此处设置是否是手动刷新数据，默认false非手动刷新数据</br>
     * false读取缓存数据、true读取非缓存数据
     *
     * @param isForceLoad
     */
    public void setForceLoad(boolean isForceLoad)
    {
        this.isForceLoad = isForceLoad;
    }

    /**
     * 是否需要缓存数据,默认不缓存,true缓存false不缓存
     *
     * @return
     */
    protected boolean isNeedCache()
    {
        return false;
    }

    public abstract String getApiMethod();

    public abstract void setApiBody(Map<String, Object> body);

    private void parseJsonObjectResult(JSONObject jsonObject)
    {
        if ("null".equals(jsonObject) || jsonObject == null)
        {
            B5MLog.i(TAG, "response--->" + null);
            return;
        }
        B5MLog.i(TAG, "response--->" + jsonObject.toString());
        try
        {
            String success = jsonObject.optString("success");
            if (FLAG_SUCCESS.equals(success))
            {
                response.parseJsonObject(jsonObject);
                apiListenrDefaultImpl.onSuccess(response);
            }
            else if (FLAG_ERROR.equals(success))
            {
                String msg = jsonObject.optString("msg");
                apiListenrDefaultImpl.onFail(0, msg);
            }
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            apiListenrDefaultImpl.onFail(0, e.getLocalizedMessage());
        }
        if (isNeedCache() && isForceLoad)
        {
            B5MCacheManage.getInstance().saveObject(jsonObject.toString(), url);
        }
    }

    private void parseJsonArrayResult(JSONArray jsonArray)
    {
        if ("null".equals(jsonArray) || jsonArray == null)
        {
            B5MLog.i(TAG, "response--->" + null);
            return;
        }
        B5MLog.i(TAG, "response--->" + jsonArray.toString());
        try
        {
            response.parseJsonArray(jsonArray);
            apiListenrDefaultImpl.onSuccess(response);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            apiListenrDefaultImpl.onFail(0, e.getLocalizedMessage());
        }
        if (isNeedCache() && isForceLoad)
        {
            B5MCacheManage.getInstance().saveObject(jsonArray.toString(), url);
        }
    }

    private void parseErrorResult(JSONObject errorResponse)
    {
        B5MLog.i(TAG, "response--->" + ("null".equals(errorResponse) || errorResponse == null ? null : errorResponse.toString()));
        apiListenrDefaultImpl.onFail(0, ("null".equals(errorResponse) || errorResponse == null ? null : errorResponse.toString()));
    }

    /**
     * 判断request是否已经开始
     * @return
     */
    public boolean isStarted()
    {
        return isStarted;
    }
}
